package com.sg.service.biz.framework.nb;


import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONArray;
import com.sg.common.util.CommonFunctionHelper;
import com.sg.common.util.RedisUtil;
import com.sg.dto.biz.framework.req.*;
import com.sg.dto.biz.framework.res.*;
import com.sg.dto.integration.component.QuerySemanticEngineDetailReqDto;
import com.sg.dto.integration.component.QuerySemanticEngineDetailRespDto;
import com.wicket.okrcomponent.common.annotations.BanAuto;
import com.wicket.okrcomponent.integration.TemplateEngineService;
import com.wicket.okrframework.common.redis.PublicInfoForRedis;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author ： 手工接入方法
 * @version 1.0
 * @since 2022/5/28 15:32
 */
@Service
public class NbUser {

    @Resource
    private RedisUtil redisClient;

    @Resource
    private TemplateEngineService fwCompTemplateEngineClient;

    /**
     * code:checkCaptchaValid
     * name:M-检测验证码是否有效（特殊方法）
     * desc:undefined
     **/
    @BanAuto
    @Trace(operationName = "M-检测验证码是否有效（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public CheckCaptchaValidRespDto checkCaptchaValid(CheckCaptchaValidReqDto reqDto) {
        CheckCaptchaValidRespDto retData = new CheckCaptchaValidRespDto();
        retData.setIsInvalid("FALSE");
        return retData;
    }

    /**
     * code:getPublicFieldCache
     * name:M1-获取接收字段（特殊方法）
     * desc:undefined
     * gen by moon at 8/17/2022, 8:01:09 PM
     **/
    @Trace(operationName = "M1-获取接收字段（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public QueryReceiveFieldDetailRespDto queryReceiveFieldDetail(QueryReceiveFieldDetailReqDto reqDto) {
        QueryReceiveFieldDetailRespDto retData = BeanUtil.toBean(reqDto, QueryReceiveFieldDetailRespDto.class);
        return retData;
    }

    /**
     * code:calculationMethod
     * name:M-计算方法（特殊方法）
     * desc:undefined
     * gen by moon at 8/25/2022, 6:28:03 AM
     **/
    @Trace(operationName = "M-计算方法（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public CalculationMethodRespDto calculationMethod(CalculationMethodReqDto reqDto) {
        CalculationMethodRespDto retData = new CalculationMethodRespDto();
        Date currentDate = CommonFunctionHelper.getCurrentTime();
        Long span = currentDate.getTime() - reqDto.getLastLockoutTime().getTime();
        span = span / 1000;
        if (span > reqDto.getThresholdValue().longValue()) {
            retData.setIsInvalid("TRUE");
        } else {
            retData.setIsInvalid("FALSE");
        }
        return retData;
    }

    /**
     * code:generateToken
     * name:M-生成Token（特殊方法）
     * desc:undefined
     * gen by moon at 8/25/2022, 6:28:19 AM
     **/
    @Trace(operationName = "M-生成Token（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public GenerateTokenRespDto generateToken(GenerateTokenReqDto reqDto) {
        GenerateTokenRespDto retData = new GenerateTokenRespDto();
        retData.setToken(UUID.randomUUID().toString().replaceAll("-", ""));
        return retData;
    }

    /**
     * code:clearTokenFromRedis
     * name:M-Redis清空用户Token（特殊方法）
     * desc:undefined
     * gen by moon at 8/25/2022, 6:28:20 AM
     **/
    @Trace(operationName = "M-Redis清空用户Token（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ClearTokenFromRedisRespDto clearTokenFromRedis(ClearTokenFromRedisReqDto reqDto) {
        String token = (String) redisClient.get("登录令牌" + ":" + "token-" + reqDto.getOriginalRoleMemberId());
        if (token == null || token.isEmpty()) {
            return new ClearTokenFromRedisRespDto();
        }
        redisClient.delete("登录令牌" + ":" + token);
        redisClient.delete("登录令牌" + ":" + "token-" + reqDto.getOriginalRoleMemberId());
        return new ClearTokenFromRedisRespDto();
    }

    /**
     * code:putPublicInfoToRedis
     * name:M-公共信息存储Redis（特殊方法）
     * desc:undefined
     * gen by moon at 8/25/2022, 6:28:21 AM
     **/
    @Trace(operationName = "M-公共信息存储Redis（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public PutPublicInfoToRedisRespDto putPublicInfoToRedis(PutPublicInfoToRedisReqDto reqDto) {
        try {
            PublicInfoForRedis info = BeanUtil.toBean(reqDto, PublicInfoForRedis.class);
            Object jo = JSONArray.toJSON(info);
            redisClient.set("登录令牌" + ":" + "token-" + info.getOriginalRoleMemberId(), reqDto.getToken());
            redisClient.set("登录令牌" + ":" + reqDto.getToken(), jo.toString(), 3600L, TimeUnit.SECONDS);
        } catch (Exception ex) {
        }
        return new PutPublicInfoToRedisRespDto();
    }

    /**
     * code:generateSemanticInstance
     * name:M1-自动生成语义内容（男士）
     * desc:undefined
     * gen by moon at 8/27/2022, 5:46:11 PM
     **/
    @Trace(operationName = "M1-自动生成语义内容（男士）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public AutoAenerateSemanticContentRespDto autoAenerateSemanticContent(AutoAenerateSemanticContentReqDto reqDto) {
        boolean bRetFlag = false;
        AutoAenerateSemanticContentRespDto retData = new AutoAenerateSemanticContentRespDto();
        String retConent = "";
        QuerySemanticEngineDetailReqDto querySemanticEngineDetailReqDto = new QuerySemanticEngineDetailReqDto();
        querySemanticEngineDetailReqDto.setTemplateSemanticEngineCode("FORGOT_PWD_RESET_NOTICE");
        QuerySemanticEngineDetailRespDto querySemanticEngineDetailRespDto = fwCompTemplateEngineClient.querySemanticEngineDetail(querySemanticEngineDetailReqDto).getData();
        if (querySemanticEngineDetailRespDto != null && querySemanticEngineDetailRespDto.getTemplateEngineTemplate() != null) {
            String idCardName = "\\{idCardName}";
            String userRespectName = "\\{userRespectName}";
            if (reqDto.getIdCardName() != null && !reqDto.getIdCardName().isEmpty()) {
                bRetFlag = true;
                retConent = querySemanticEngineDetailRespDto.getTemplateEngineTemplate().replaceAll(idCardName, reqDto.getIdCardName());
            } else {
                retConent = querySemanticEngineDetailRespDto.getTemplateEngineTemplate().replaceAll(idCardName, "---");
            }

            if (reqDto.getUserRespectName() != null && !reqDto.getUserRespectName().isEmpty()) {
                retConent = retConent.replaceAll(userRespectName, reqDto.getUserRespectName());
            } else {
                retConent = retConent.replaceAll(userRespectName, "---");
            }


            if (retConent != null && !retConent.isEmpty()) {
                retConent = retConent.replaceAll("---", "");
                retConent = retConent.replaceAll("（）", "");
                retData.setObjectName(retConent);
            }

            if (bRetFlag) {
                return retData;
            }

        }
        return retData;
    }

    /**
     * code:implementAuthLoginOut
     * name:M1-执行统一认证退出登录（特殊方法）
     * desc:undefined
     * gen by moon at 9/12/2023, 7:56:17 PM
     **/
    @Trace(operationName = "M1-执行统一认证退出登录（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementAuthLoginOutRespDto implementAuthLoginOut(ImplementAuthLoginOutReqDto reqDto) {
        ImplementAuthLoginOutRespDto retData = new ImplementAuthLoginOutRespDto();
        String url = CommonFunctionHelper.constructRedirectUrl(reqDto.getAuthLogoutUrl(), "service", reqDto.getAuthLoginUrl());
        retData.setAuthLoginUrl(url);
        return retData;
    }

    private Map<String, String> extractReqValues(ObtainAuthAccountInfoReqDto req) {
        Map<String, String> retData = new HashMap<>();
        Field[] declaredFields = req.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            if (!field.getName().contains("Field")) {
                continue;
            }
            field.setAccessible(true);
            String value = null;
            try {
                value = (String) field.get(req);
                if (value != null) {
                    retData.put(field.getName(), value);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return retData;
    }

    private Map<String, Field> extractRetField(ObtainAuthAccountInfoRespDto req) {
        Map<String, Field> retData = new HashMap<>();
        Field[] declaredFields = req.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            retData.put(field.getName() + "Field", field);
        }
        return retData;
    }

    /**
     * code:obtainAuthAccountInfo
     * name:M1-调用统一认证接口（特殊方法）
     * desc:undefined
     * gen by moon at 9/12/2023, 7:56:35 PM
     **/
    @Trace(operationName = "M1-调用统一认证接口（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public String getCasInfo(String ticketUrl) {
        String responseBody = "";
        OkHttpClient client = new OkHttpClient();
        try {

            Request request = new Request.Builder()
                    .url(ticketUrl)
                    .build();
            Response response = client.newCall(request).execute();
            responseBody = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseBody;
    }

    /**
     * code:obtainAuthAccountInfo
     * name:M1-获取统一认证用户信息（特殊方法）
     * desc:undefined
     * gen by moon at 9/12/2023, 7:56:35 PM
     **/
    @Trace(operationName = "M1-获取统一认证用户信息（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ObtainAuthAccountInfoRespDto obtainAuthAccountInfo(ObtainAuthAccountInfoReqDto reqDto) {
        ObtainAuthAccountInfoRespDto retData = new ObtainAuthAccountInfoRespDto();
        Map<String, String> reqValues = extractReqValues(reqDto);
        Map<String, Field> retFields = extractRetField(retData);


        String service = reqDto.getAppCallBackUrl();
        String ticketUrl = reqDto.getAuthCheckTicketUrl() + "serviceValidate?ticket=" + reqDto.getAuthTicket() + "&service=" + service;
        String responseBody = getCasInfo(ticketUrl);

        redisClient.set("获取统一认证用户信息报文", responseBody);

        for (Map.Entry<String, String> oneReq : reqValues.entrySet()) {
            Field target = retFields.get(oneReq.getKey());
            if (target != null) {
                int startIndex = responseBody.indexOf(oneReq.getValue()) + oneReq.getValue().length();
                if (startIndex == -1) {
                    continue;
                }
                int endIndex = responseBody.indexOf(oneReq.getValue().replace("<cas:", "</cas:"));
                if (endIndex == -1) {
                    continue;
                }
                String targetValue = responseBody.substring(startIndex, endIndex).trim();
                try {
                    target.set(retData, targetValue);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return retData;
    }

    /**
     * code:splicingUnifiedAuthenticationAddresses
     * name:M1拼第三方统一认证的登录地址（特殊方法）
     * desc:undefined
     * gen by moon at 12/20/2023, 9:17:40 PM
     **/
    @Trace(operationName = "M1拼第三方统一认证的登录地址（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementObtainUnifiedAuthenticationLoginInformationRespDto implementObtainUnifiedAuthenticationLoginInformation(ImplementObtainUnifiedAuthenticationLoginInformationReqDto reqDto) {
        ImplementObtainUnifiedAuthenticationLoginInformationRespDto retData = new ImplementObtainUnifiedAuthenticationLoginInformationRespDto();
        String url = CommonFunctionHelper.constructRedirectUrl(reqDto.getAuthLoginUrl(), "service", reqDto.getAppCallBackUrl(), false, false);
        retData.setSplicingAuthAddresses(url);
        return retData;
    }
    //手工接入方法
}
